<template>
  <div class="tableMain">
    <!-- 按钮操作 -->
    <div class="tableHeader">
      <slot
        name="tableHeader"
        :selected-list-ids="selectedListIds"
        :selected-list="selectedList"
        :is-selected="isSelected"
      />
      <div class="search">
        <el-input
          v-model="initParam[Object.keys(initParam)[0]]"
          style="max-width: 600px"
          placeholder="请输入搜索内容"
          class="input-with-select"
          @change="getTableList(true)"
          clearable
        >
          <template #append>
            <el-button :icon="Search" @click="getTableList(true)" />
          </template>
        </el-input>
      </div>
    </div>

    <!-- 表单主体 -->

    <div class="tableContent">
      <el-table
        v-if="isTable"
        ref="tableRef"
        :data="tableDate"
        :border="border"
        v-bind="$attrs"
        :row-key="rowKey"
        @selection-change="selectionChange"
      >
        <!-- 对传进来的column进行处理 -->
        <template v-for="item in tableColumns" :key="item">
          <!-- selection || index || expand -->
          <el-table-column
            v-if="
              item.type && ['selection', 'index', 'expand'].includes(item.type)
            "
            v-bind="item"
            :align="item.align ?? 'center'"
            :reserve-selection="item.type == 'selection'"
          >
            <template v-if="item.type == 'expand'" #default="scope">
              <component :is="item.render" v-bind="scope" v-if="item.render">
              </component>
              <slot v-else :name="item.type" v-bind="scope"></slot>
            </template>
          </el-table-column>

          <el-table-column
            v-else-if="item.render"
            v-bind="item"
            :align="item.align ?? 'center'"
          >
            <template #default="scope">
              <component :is="item.render" v-bind="scope" v-if="item.render">
              </component>
              <slot :name="item.type" v-bind="scope"></slot>
            </template>
          </el-table-column>

          <el-table-column
            v-else
            v-bind="item"
            :align="item.align ?? 'center'"
          ></el-table-column>
        </template>

        <!-- 默认插槽 主要放操作列的 -->
        <slot></slot>
      </el-table>
      <slot name="tableContent"></slot>
    </div>

    <!-- 分页 -->
    <Pagination
      v-if="pagination"
      :pageTotal="pageable.total"
      :current="1"
      :pageSize="pageable.size"
      @currentChange="currentChange"
      @sizeChange="sizeChange"
    >
    </Pagination>
  </div>
</template>

<script setup lang="ts" name="Tables">
import { useTable } from "@/hooks/useTable";
import { onMounted, ref, watch } from "vue";
import { Search } from "@element-plus/icons-vue";
import Pagination from "@/components/Pagination/Pagination.vue";
import { useSelection } from "@/hooks/useSelection";

export interface ProTableProps {
  isTable?: boolean; //中间部分是否是表格(默认是表格)
  columns?: any[]; // 列配置项  ==> 必传
  initParam: any; // 初始化请求参数 ==> 非必传（默认为{}）
  requestApi?: (params: any) => Promise<any>; // 请求表格数据的 api ==> 非必传
  requestAuto?: boolean; // 是否自动执行请求 api ==> 非必传（默认为true）
  pagination?: boolean; // 是否需要分页组件 ==> 非必传（默认为true）
  border?: boolean; // 是否带有纵向边框 ==> 非必传（默认为true）
  rowKey?: string; // 行数据的 Key，用来优化 Table 的渲染，当表格数据多选时，所指定的 _id ==> 非必传（默认为 _id）
  dataCallback?: (data: any) => any; // 返回数据的回调函数，可以对数据进行处理 ==> 非必传
}
// 接受父组件参数，配置默认值
const props = withDefaults(defineProps<ProTableProps>(), {
  columns: () => [],
  initParam: {},
  requestAuto: true,
  pagination: true,
  border: true,
  rowKey: "_id",
  isTable: true,
});
// 表格 DOM 元素
const tableRef = ref();

const { getTableList, tableDate, pageable, currentChange, sizeChange } =
  useTable(
    props.requestApi,
    props.initParam,
    props.pagination,
    props.dataCallback
  );
// 表格多选 Hooks
const { selectionChange, selectedList, selectedListIds, isSelected } =
  useSelection(props.rowKey);
// 初始化请求
onMounted(() => {
  props.requestAuto && getTableList();
});

// 清空选中数据列表
const clearSelection = () => tableRef.value!.clearSelection();

// 监听页面 initParam 改化，重新获取表格数据
watch(() => props.initParam, getTableList, { deep: true });

// 接收 columns 并设置为响应式
const tableColumns = ref<any[]>(props.columns);
// 暴露给父组件的参数和方法(外部需要什么，都可以从这里暴露出去)
defineExpose({
  getTableList,
  clearSelection,
  tableDate,
});
</script>

<style scoped lang="scss">
@import "./index.scss";
</style>
